package org.jeecg.modules.cosmetic.handler;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.cosmetic.constant.enums.DeclareEntryEnum;
import org.jeecg.modules.cosmetic.entity.TDeclareChiEntry;
import org.jeecg.modules.cosmetic.entity.TDeclareEngEntry;
import org.jeecg.modules.cosmetic.entity.TPackageAudit;
import org.jeecg.modules.cosmetic.entity.TPackageResult;
import org.jeecg.modules.cosmetic.model.dto.PackageResultDTO;
import org.jeecg.modules.cosmetic.model.vo.PackageAuditVO;
import org.jeecg.modules.cosmetic.service.ITDeclareChiEntryService;
import org.jeecg.modules.cosmetic.service.ITDeclareEngEntryService;
import org.jeecg.modules.cosmetic.service.ITPackageAuditService;
import org.jeecg.modules.cosmetic.service.ITPackageResultService;
import org.jeecg.modules.cosmetic.utils.PackageUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

@Service
@Slf4j
public class PackageAuditHandler {

    @Resource
    private ITDeclareChiEntryService itDeclareChiEntryService;

    @Resource
    private ITDeclareEngEntryService itDeclareEngEntryService;

    @Resource
    private ITPackageAuditService itPackageAuditService;

    @Resource
    private ITPackageResultService itPackageResultService;

    /**
     * 包装审核提交方法
     * @param vo
     * @return
     */
    @Transactional
    @DS("cosmetic-datasource")
    public Result<PackageResultDTO> submitPackAudit(PackageAuditVO vo) {
        if (StringUtils.isBlank(vo.getMessage())) {
            log.error("录入的宣称信息为空");
            return Result.error("录入的宣称信息为空");
        }
        Map<String, Map<String, String>> mapProhibited = null;
        Map<String, Map<String, String>> mapHigh = null;
        Map<String, Map<String, String>> mapLow = null;
        Map<String, Map<String, String>> mapEfficacy = null;
        // 全英文的判断逻辑
        if (!PackageUtil.hasChinese(vo.getMessage())) {
            Map<Integer, List<TDeclareEngEntry>> declareEngEntryMap = queryDeclareEngEntry();
            if (CollectionUtil.isEmpty(declareEngEntryMap)) {
                log.error("英文宣称条目为空，请维护");
                return Result.error("英文宣称条目为空，请维护");
            }
            mapProhibited = packageDeclareEngWords(vo.getMessage(), declareEngEntryMap, DeclareEntryEnum.PROHIBITED.getLevel(), DeclareEntryEnum.PROHIBITED.getMsg());
            mapHigh = packageDeclareEngWords(vo.getMessage(), declareEngEntryMap, DeclareEntryEnum.HIGH.getLevel(), DeclareEntryEnum.HIGH.getMsg());
            mapLow = packageDeclareEngWords(vo.getMessage(), declareEngEntryMap, DeclareEntryEnum.LOW.getLevel(), DeclareEntryEnum.LOW.getMsg());
            mapEfficacy = packageDeclareEngWords(vo.getMessage(), declareEngEntryMap, DeclareEntryEnum.EFFICACY.getLevel(), null);
        } else {
            Map<Integer, List<TDeclareChiEntry>> declareChiEntryMap = queryDeclareChiEntry();
            if (CollectionUtil.isEmpty(declareChiEntryMap)) {
                log.error("中文宣称条目为空，请维护");
                return Result.error("中文宣称条目为空，请维护");
            }
            mapProhibited = packageDeclareChiWords(vo.getMessage(), declareChiEntryMap, DeclareEntryEnum.PROHIBITED.getLevel(), DeclareEntryEnum.PROHIBITED.getMsg());
            mapHigh = packageDeclareChiWords(vo.getMessage(), declareChiEntryMap, DeclareEntryEnum.HIGH.getLevel(), DeclareEntryEnum.HIGH.getMsg());
            mapLow = packageDeclareChiWords(vo.getMessage(), declareChiEntryMap, DeclareEntryEnum.LOW.getLevel(), DeclareEntryEnum.LOW.getMsg());
            mapEfficacy = packageDeclareChiWords(vo.getMessage(), declareChiEntryMap, DeclareEntryEnum.EFFICACY.getLevel(), null);
        }

        // 存储子表（结果表）数据
        AtomicInteger sizeProhibited = new AtomicInteger(0);
        AtomicInteger sizeHigh = new AtomicInteger(0);
        AtomicInteger sizeLow = new AtomicInteger(0);
        AtomicInteger sizeEfficacy = new AtomicInteger(0);
        traversalMap(mapProhibited, sizeProhibited, 1, 1);
        traversalMap(mapHigh, sizeHigh, 2, 2);
        traversalMap(mapLow, sizeLow, 3, 3);
        traversalMap(mapEfficacy, sizeEfficacy, 4, 4);

        // 先保存主表的数据在同步更新子表对应的主表ID
        TPackageAudit tPackageAudit = new TPackageAudit();
        tPackageAudit.setMessage(vo.getMessage());
        tPackageAudit.setProhibitedCount(sizeProhibited.get());
        tPackageAudit.setHighCount(sizeHigh.get());
        tPackageAudit.setLowCount(sizeLow.get());
        tPackageAudit.setEfficacyCount(sizeEfficacy.get());
        itPackageAuditService.save(tPackageAudit);
        List<TPackageResult> tPackageResults = itPackageResultService.list(new LambdaQueryWrapper<TPackageResult>().isNull(TPackageResult::getAudId));
        if (CollectionUtil.isNotEmpty(tPackageResults)) {
            tPackageResults.forEach(i -> {
                i.setAudId(tPackageAudit.getId());
            });
        }
        itPackageResultService.updateBatchById(tPackageResults);

        // 封装高亮词
        Map<String, Map<String, String>> finalMapHigh = mapHigh;
        Map<String, Map<String, String>> finalMapLow = mapLow;
        LinkedHashSet<String> listProhibited = new LinkedHashSet<>();
        LinkedHashSet<String> listHigh = new LinkedHashSet<>();
        LinkedHashSet<String> listLowMid = new LinkedHashSet<>();
        LinkedHashSet<String> listLow = new LinkedHashSet<>();
        LinkedHashSet<String> listEfficacy = new LinkedHashSet<>();
        if (CollectionUtil.isNotEmpty(mapProhibited.get("违禁词").values())) {
            mapProhibited.forEach((keyP, valueP) -> {
                valueP.forEach((kP, vP) -> {
                    listProhibited.add(kP);
                    finalMapHigh.forEach((keyH, valueH) -> {
                        valueH.forEach((kH, vH) -> {
                            if (!kP.contains(kH)) {
                                listHigh.add(kH);
                            }
                        });
                    });
                    finalMapLow.forEach((keyL, valueL) -> {
                        valueL.forEach((kL, vL) -> {
                            if (!kP.contains(kL)) {
                                listLowMid.add(kL);
                            }
                        });
                    });
                });
            });
        }
        if (CollectionUtil.isNotEmpty(mapHigh.get("高风险词").values())){
            mapHigh.forEach((keyH, valueH) -> {
                valueH.forEach((kH, vH) -> {
                    listHigh.add(kH);
                    finalMapLow.forEach((keyL, valueL) -> {
                        valueL.forEach((kL, vL) -> {
                            if (!kH.contains(kL)) {
                                listLowMid.add(kL);
                            }
                        });
                    });
                });
            });
        }
        if (CollectionUtil.isNotEmpty(mapLow.get("低风险词").values())) {
            mapLow.forEach((keyL, valueL) -> {
                valueL.forEach((kl, vl) -> {
                    listLow.add(kl);
                });
            });
        }
        if (CollectionUtil.isNotEmpty(listHigh) && CollectionUtil.isNotEmpty(listLowMid)) {
            listHigh.forEach(items -> {
                listLowMid.forEach(item -> {
                    if (!items.contains(item)) {
                        listLow.add(item);
                    }
                });
            });
        }
        mapEfficacy.forEach((keyE, valueE) -> {
            listEfficacy.add(keyE);
        });

        // 返回封装后的数据
        PackageResultDTO packageResultDTO = new PackageResultDTO();
        packageResultDTO.setProhibitedSize(sizeProhibited.get());
        packageResultDTO.setHighSize(sizeHigh.get());
        packageResultDTO.setLowSize(sizeLow.get());
        packageResultDTO.setEfficacySize(sizeEfficacy.get());
        packageResultDTO.setMapProhibited(mapProhibited);
        packageResultDTO.setMapHigh(mapHigh);
        packageResultDTO.setMapLow(mapLow);
        packageResultDTO.setMapEfficacy(mapEfficacy);
        packageResultDTO.setColourProhibited(listProhibited);
        packageResultDTO.setColourHigh(listHigh);
        packageResultDTO.setColourLow(listLow);
        packageResultDTO.setColourEfficacy(listEfficacy);
        packageResultDTO.setMessage(vo.getMessage());
        return Result.OK(packageResultDTO);
    }

    /**
     * 遍历封装违禁词，高风险词，低风险词的 Map，并把结果保存到结果表内
     * @param mapMap
     * @param size
     * @param level
     */
    private void traversalMap(Map<String, Map<String, String>> mapMap, AtomicInteger size, int level, int dif) {
        if (ObjectUtil.isNotNull(mapMap)) {
            mapMap.forEach((keys, values) -> {
                if (dif == 4) {
                    size.set(mapMap.size());
                } else {
                    // 拿到数组的长度
                    size.set(values.size());
                }
                // 保存子表数据
                values.forEach((key, value) -> {
                    TPackageResult tPackageResult = new TPackageResult();
                    tPackageResult.setLevel(level);
                    if (dif == 4) {
                        tPackageResult.setWords(keys);
                        tPackageResult.setEfficacy(key);
                    } else {
                        tPackageResult.setWords(key);
                        tPackageResult.setAdvice(value);
                    }
                    itPackageResultService.save(tPackageResult);
                });
            });
        }
    }

    /**
     * 中文违禁词，高风险词，低风险词和功效类别
     * @param message
     * @param declareChiEntryMap
     * @param level
     * @param msg
     * @return
     */
    private Map<String, Map<String, String>> packageDeclareChiWords(String message, Map<Integer, List<TDeclareChiEntry>> declareChiEntryMap, Integer level, String msg) {
        Map<String, String> map = new HashMap<>();
        Map<String, Map<String, String>> mapMap = new HashMap<>();
        List<TDeclareChiEntry> list = declareChiEntryMap.get(level);
        // 功效类别的词
        if (level.equals(DeclareEntryEnum.EFFICACY.getLevel())) {
            for (TDeclareChiEntry tDeclareChiEntry : list) {
                if (message.contains(tDeclareChiEntry.getChiWords())) {
                    Map<String, String> mapChi = new HashMap<>();
                    mapChi.put(tDeclareChiEntry.getEfficacy(), tDeclareChiEntry.getAdvice());
                    mapMap.put(tDeclareChiEntry.getChiWords(), mapChi);
                }
            }
            return mapMap;
        }
        // 违禁词，高风险词，低风险词
        for (TDeclareChiEntry tDeclareChiEntry : list) {
            if (message.contains(tDeclareChiEntry.getChiWords())) {
                map.put(tDeclareChiEntry.getChiWords(), tDeclareChiEntry.getAdvice());
            }
        }
        mapMap.put(msg, map);
        return mapMap;
    }

    /**
     * 英文违禁词，高风险词，低风险词和功效类别
     * @param message
     * @param declareEngEntryMap
     * @param level
     * @param msg
     * @return
     */
    private Map<String, Map<String, String>> packageDeclareEngWords(String message, Map<Integer, List<TDeclareEngEntry>> declareEngEntryMap, Integer level, String msg) {
        Map<String, String> map = new HashMap<>();
        Map<String, Map<String, String>> mapMap = new HashMap<>();
        List<TDeclareEngEntry> list = declareEngEntryMap.get(level);
        // 功效类别的词
        if (level.equals(DeclareEntryEnum.EFFICACY.getLevel())) {
            for (TDeclareEngEntry tDeclareEngEntry : list) {
                if (message.contains(tDeclareEngEntry.getEngWords())) {
                    Map<String, String> mapEng = new HashMap<>();
                    mapEng.put(tDeclareEngEntry.getEfficacy(), tDeclareEngEntry.getAdvice());
                    mapMap.put(tDeclareEngEntry.getEngWords(), mapEng);
                }
            }
            return mapMap;
        }
        // 违禁词，高风险词，低风险词
        for (TDeclareEngEntry tDeclareEngEntry : list) {
            if (message.contains(tDeclareEngEntry.getEngWords())) {
                map.put(tDeclareEngEntry.getEngWords(), tDeclareEngEntry.getAdvice());
            }
        }
        mapMap.put(msg, map);
        return mapMap;
    }

    /**
     * 查询中文违禁词，高风险词，低风险词，功效类别
     * @return
     */
    public Map<Integer, List<TDeclareChiEntry>> queryDeclareChiEntry() {
        List<TDeclareChiEntry> entryList = itDeclareChiEntryService.list();
        Map<Integer, List<TDeclareChiEntry>> listMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(entryList)) {
            List<TDeclareChiEntry> listProhibited = Lists.newArrayList();
            List<TDeclareChiEntry> listHigh = Lists.newArrayList();
            List<TDeclareChiEntry> listLow = Lists.newArrayList();
            List<TDeclareChiEntry> listEfficacy = Lists.newArrayList();
            for (TDeclareChiEntry tDeclareChiEntry : entryList) {
                switch (tDeclareChiEntry.getLevel()) {
                    case 1:
                        listProhibited.add(tDeclareChiEntry);
                        break;
                    case 2:
                        listHigh.add(tDeclareChiEntry);
                        break;
                    case 3:
                        listLow.add(tDeclareChiEntry);
                        break;
                    case 4:
                        listEfficacy.add(tDeclareChiEntry);
                        break;
                    default:
                        log.error("关键词类型不明确：{}", tDeclareChiEntry);
                        break;
                }
            }
            listMap.put(DeclareEntryEnum.PROHIBITED.getLevel(), listProhibited);
            listMap.put(DeclareEntryEnum.HIGH.getLevel(), listHigh);
            listMap.put(DeclareEntryEnum.LOW.getLevel(), listLow);
            listMap.put(DeclareEntryEnum.EFFICACY.getLevel(), listEfficacy);
        }
        return listMap;
    }

    /**
     * 查询英文违禁词，高风险词，低风险词，功效类别
     * @return
     */
    public Map<Integer, List<TDeclareEngEntry>> queryDeclareEngEntry() {
        List<TDeclareEngEntry> entryList = itDeclareEngEntryService.list();
        Map<Integer, List<TDeclareEngEntry>> listMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(entryList)) {
            List<TDeclareEngEntry> listProhibited = Lists.newArrayList();
            List<TDeclareEngEntry> listHigh = Lists.newArrayList();
            List<TDeclareEngEntry> listLow = Lists.newArrayList();
            List<TDeclareEngEntry> listEfficacy = Lists.newArrayList();
            for (TDeclareEngEntry tDeclareEngEntry : entryList) {
                switch (tDeclareEngEntry.getLevel()) {
                    case 1:
                        listProhibited.add(tDeclareEngEntry);
                        break;
                    case 2:
                        listHigh.add(tDeclareEngEntry);
                        break;
                    case 3:
                        listLow.add(tDeclareEngEntry);
                        break;
                    case 4:
                        listEfficacy.add(tDeclareEngEntry);
                        break;
                    default:
                        log.error("关键词类型不明确：{}", tDeclareEngEntry);
                        break;
                }
            }
            listMap.put(DeclareEntryEnum.PROHIBITED.getLevel(), listProhibited);
            listMap.put(DeclareEntryEnum.HIGH.getLevel(), listHigh);
            listMap.put(DeclareEntryEnum.LOW.getLevel(), listLow);
            listMap.put(DeclareEntryEnum.EFFICACY.getLevel(), listEfficacy);
        }
        return listMap;
    }
}
